package com.zgh.opcua.manager;

import com.zgh.opcua.config.OpcContext;
import com.zgh.opcua.entity.DataValueEntity;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName KepwareDataManager
 * @Description Kepserver数据管理器
 * @Author Administrator
 * @Date 17:37 2025/11/6
 * @Version 1.0
 */
@Slf4j
public class KepwareDataManager {

    // 批量缓冲队列
    private static volatile BlockingQueue<DataValueEntity> bufferQueue;
    // 唯一的单例实例，
    private static final KepwareDataManager INSTANCE = new KepwareDataManager();

    private KepwareDataManager() {
    }

    /**
     * 获取单例实例（线程安全）
     */
    public static KepwareDataManager getInstance() {
        return INSTANCE;
    }

    //创建队列并开启线程
    public void createBufferQueue() {
        if (bufferQueue == null) {
            synchronized (KepwareDataManager.class) {
                if (bufferQueue == null) {
                    bufferQueue = new LinkedBlockingQueue<>(OpcContext.getQueueCapacity());
                    Thread saverThread = new Thread(this::saveLoop, "opcua-batch-saver");
                    saverThread.setDaemon(true);
                    saverThread.start();
                }
            }
        }
    }


    /**
     * 将节点数据放入队列
     */
    public void addData(DataValueEntity entity) {
        try {
            if (!bufferQueue.offer(entity, OpcContext.getOfferTimeoutMs(), TimeUnit.MILLISECONDS)) {
                log.warn("缓存队列已满，丢弃数据: {}", entity);
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.error("放入队列中断", e);
        }
    }

    /**
     * 每多少秒或累积一定数量后，批量保存一次
     */
    private void saveLoop() {
        List<DataValueEntity> batch = new ArrayList<>();
        long lastFlushTime = System.currentTimeMillis();

        try {
            while (true) {
                DataValueEntity dataValueEntity = bufferQueue.poll(OpcContext.getPollTimeoutMs(), TimeUnit.MILLISECONDS);
                if (dataValueEntity != null) {
                    batch.add(dataValueEntity);
                }

                long now = System.currentTimeMillis();

                // 条件：累计数量或时间间隔达到阈值时执行批量保存
                if (batch.size() >= OpcContext.getBatchSize() || (now - lastFlushTime > OpcContext.getFlushIntervalMs() && !batch.isEmpty())) {
                    saveBatchToDB(batch);
                    batch.clear();
                    lastFlushTime = now;
                }
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.warn("批量保存线程被中断");
        }
    }

    /**
     * 批量写入数据库（或其他持久层）
     */
    private void saveBatchToDB(List<DataValueEntity> batch) {
        if (batch.isEmpty()) {
            return;
        }

        try {
            log.info("批量保存 {} 条节点数据", batch.size());
            for (DataValueEntity dataValue : batch) {
                log.debug("soleCode={} | alue={} | timestamp={}",
                        dataValue.getSoleCode(), dataValue.getValue(), dataValue.getTimestamp());
            }
        } catch (Exception e) {
            log.error("批量保存失败", e);
        }
    }


    public static void main(String[] args) throws Exception {

        // 从配置上下文读取参数
        OpcContext.setQueueCapacity(10000);
        OpcContext.setBatchSize(10000);
        OpcContext.setFlushIntervalMs(10000);
        OpcContext.setPollTimeoutMs(500);
        OpcContext.setOfferTimeoutMs(100);

        KepwareDataManager instance = KepwareDataManager.getInstance();
        instance.createBufferQueue();

        int num = 1;
        while (true) {
            DataValueEntity record = new DataValueEntity(
                    String.valueOf("nodeId.getIdentifier()"),
                    num++,
                    System.currentTimeMillis()
            );
            // 将变化数据放入缓冲队列
            instance.addData(record);
            //Thread.sleep(1000);
        }

    }
}
